package com.gagakuai.concurrent;

import sun.security.util.SecurityConstants;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.atomic.AtomicInteger;

/*
 * @program: common-starters
 * @description: 【任务执行框架】的工厂，该工厂负责生产 【任务执行框架】对象 和Callable类型的任务对象、线程工厂对象
 * @author: houhong
 * @create: 2023-02-19 20:13
 */
public class Executors {

    private Executors() {
    }

    /*▼ 【工作池】 ████████████████████████████████████████████████████████████████████████████████┓ */

    /*
     * 并行度与处理器数量相同的【工作池】/[任务执行框架]
     */
    public static ExecutorService newWorkStealingPool() {

        //// TODO: 2023/2/19
        return null;
    }


    private static final class RunnableAdapter<T> implements Callable<T> {

        private final Runnable task;
        private final T result;

        public RunnableAdapter(Runnable runnable, T result) {
            this.task = runnable;
            this.result = result;
        }

        @Override
        public T call() throws Exception {
            task.run();
            return result;
        }
    }


    /*
     * 包装 runable 有返回值
     */
    public static <T> Callable<T> callable(Runnable runnable, T result) {


        if (runnable == null) {
            throw new NullPointerException();
        }
        return new RunnableAdapter<>(runnable, result);
    }


    /*
     * @Author houhong
     * @Description //TODO 默认线程工厂，创建默认线程优先级的非守护线程
     * @Date 11:30 下午 2023/2/24
     * @return {@link null}
     */
    private static class DefaultThreadfactory implements ThreadFactory {


        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private static final AtomicInteger threadNumber = new AtomicInteger(1);


        private final String namePrefix;
        private final  ThreadGroup group;


        public DefaultThreadfactory() {

            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {

            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            if(t.isDaemon()){
                t.setDaemon(true);
            }

            if(t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }

            return t;
        }




        /*
        *  特权线程工厂
        *
        */
        private static class PrivilegedThreadFactory extends DefaultThreadfactory{

            final AccessControlContext acc;

            final ClassLoader ccl;


            public PrivilegedThreadFactory() {

                super();

                SecurityManager sm = System.getSecurityManager();

                if(sm != null){
                    sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);

                    // Fail fast
                    sm.checkPermission(new RuntimePermission("setContextClassLoader"));
                }

                this.acc = AccessController.getContext();
                this.ccl = Thread.currentThread().getContextClassLoader();

            }

            @Override
            public Thread newThread(Runnable r) {


                return super.newThread(() -> AccessController.doPrivileged(new PrivilegedAction<>() {

                    @Override
                    public Void run() {
                        Thread.currentThread().setContextClassLoader(ccl);
                        r.run();
                        return null;
                    }
                }, acc));
            }
        }





    }



    public static ThreadFactory defaultThreadFactory(){

        return  new DefaultThreadfactory();
    }


}